#region File Description
//-----------------------------------------------------------------------------
// NetworkSelectionScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.GamerServices;
#endregion

namespace TankWars
{
    /// <summary>
    /// The options screen is brought up over the top of the main menu
    /// screen, and gives the user a chance to configure the game
    /// in various hopefully useful ways.
    /// </summary>
    class NetworkSelectionScreen : MenuScreen
    {
        #region Fields

        MenuEntry hostGameMenuEntry;
        MenuEntry joinGameMenuEntry;
        MenuEntry backMenuEntry;

        NetworkSessionType sessionType;

        const int maxGamers = 16;
        const int maxLocalGamers = 4;   // Must change this in "MainMenuScreen.cs" too

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public NetworkSelectionScreen(NetworkSessionType type) : base("Connect to a Network")
        {
            // Collect session type
            sessionType = type;

            // Create our menu entries.
            hostGameMenuEntry = new MenuEntry("Host a Game");
            joinGameMenuEntry = new MenuEntry("Join a Game");
            backMenuEntry = new MenuEntry("Back to Main Menu");

            // Hook up menu event handlers.
            hostGameMenuEntry.Selected += HostGameMenuEntrySelected;
            joinGameMenuEntry.Selected += JoinGameMenuEntrySelected;
            backMenuEntry.Selected += OnCancel;
            
            // Add entries to the menu.
            MenuEntries.Add(hostGameMenuEntry);
            MenuEntries.Add(joinGameMenuEntry);
            MenuEntries.Add(backMenuEntry);
        }


        #endregion

        #region Handle Input and Network Initialization


        /// <summary>
        /// Event handler for when the create as host menu entry is selected.
        /// </summary>
        void HostGameMenuEntrySelected(object sender, EventArgs e)
        {
            try
            {
                // Begin an asynchronous create network session operation.
                IAsyncResult asyncResult = NetworkSession.BeginCreate(sessionType,
                                                NetworkSessionComponent.MaxLocalGamers,
                                                NetworkSessionComponent.MaxGamers,
                                                null, null);

                // Activate the network busy screen, which will display
                // an animation until this operation has completed.
                NetworkBusyScreen busyScreen = new NetworkBusyScreen(asyncResult);

                busyScreen.OperationCompleted += CreateSessionOperationCompleted;

                ScreenManager.AddScreen(busyScreen);
            }
            catch (NetworkException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }
            catch (GamerPrivilegeException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }          
        }

        /// <summary>
        /// Event handler for when the asynchronous create network session
        /// operation has completed.
        /// </summary>
        void CreateSessionOperationCompleted(object sender, OperationCompletedEventArgs e)
        {
            try
            {
                // End the asynchronous create network session operation.
                NetworkSession networkSession = NetworkSession.EndCreate(e.AsyncResult);

                // Create a component that will manage the session we just created.
                NetworkSessionComponent.Create(ScreenManager, networkSession);

                // Go to the lobby screen.
                ScreenManager.AddScreen(new LobbyScreen(networkSession));
            }
            catch (NetworkException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }
            catch (GamerPrivilegeException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }
        }

        /// <summary>
        /// Event handler for when the join game entry is selected.
        /// </summary>
        void JoinGameMenuEntrySelected(object sender, EventArgs e)
        {

            try
            {
                // Begin an asynchronous find network sessions operation.
                IAsyncResult asyncResult = NetworkSession.BeginFind(sessionType,
                                                NetworkSessionComponent.MaxLocalGamers,
                                                null, null, null);

                // Activate the network busy screen, which will display
                // an animation until this operation has completed.
                NetworkBusyScreen busyScreen = new NetworkBusyScreen(asyncResult);

                busyScreen.OperationCompleted += FindSessionsOperationCompleted;

                ScreenManager.AddScreen(busyScreen);
            }
            catch (NetworkException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }
            catch (GamerPrivilegeException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }           
        }

        /// <summary>
        /// Event handler for when the asynchronous find network sessions
        /// operation has completed.
        /// </summary>
        void FindSessionsOperationCompleted(object sender, OperationCompletedEventArgs e)
        {
            try
            {
                // End the asynchronous find network sessions operation.
                AvailableNetworkSessionCollection availableSessions = NetworkSession.EndFind(e.AsyncResult);

                if (availableSessions.Count == 0)
                {
                    // If we didn't find any sessions, display an error.
                    availableSessions.Dispose();

                    ScreenManager.AddScreen(new MessageBoxScreen("Error: No network session found", false));
                }
                else
                {
                    // If we did find some sessions, proceed to the JoinSessionScreen.
                    ScreenManager.AddScreen(new JoinSessionScreen(availableSessions));
                }
            }
            catch (NetworkException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }
            catch (GamerPrivilegeException exception)
            {
                ScreenManager.AddScreen(new NetworkErrorScreen(exception));
            }
        }

        #endregion        
    }
}
